Ext.apply(Fxt, {
    emptyFn: function() {},
    buildNodePkg: function(node) {
        var pkgs = [];
        do {
            var value = node.get('value');
            if (value) {
                pkgs.push(node.get('value'));
            }
            node = node.parentNode;
        } while (node != null);
        return pkgs.reverse().join('.');
    },
    uuid: function() {
        var uuid = Ext.data.IdGenerator.get('uuid').generate();
        return uuid.replace(/-/g, '');
    },
    selectOneRow: function(grid, callback) {
        var selModel = grid.getSelectionModel(),
            selCount = selModel.getCount();
        if (selCount !== 1) {
            Fxt.alertInfo('请只选择一行');
            return;
        }
        var records = selModel.getSelection();
        var record = records[0];
        callback(record);
    },
    selectRows: function(grid, callback) {
        var selModel = grid.getSelectionModel(),
            selCount = selModel.getCount();
        if (selCount == 0) {
            Fxt.alertInfo('请至少选择一行');
            return;
        }
        var records = selModel.getSelection();
        callback(records);
    },
    selectRecords: function(grid, records) {
        var selectRecords = [];
        Ext.each(records, function(record) {
            if (record.get('checked')) {
                selectRecords.push(record);
            }
        });
        grid.getSelectionModel().select(selectRecords);
    },
    getSelectIds: function(grid, callback) {
        var ids = [];
        var selModel = grid.getSelectionModel(),
            records = selModel.getSelection();
        Ext.each(records, function(record) {
            ids.push(record.get('id'));
        });
        if (ids.length == 0) {
            Fxt.alertInfo('请选择数据');
            return [];
        } else {
            if (callback) {
                callback(ids);
            } else {
                return ids;
            }
        }
    },
    ajax: function(config) {
        var waitMsg = config.waitMsg === false ? false : '执行中...';
        if (waitMsg) {
            var maskCmp = config.maskCmp;
            if (maskCmp) {
                maskCmp.setLoading(waitMsg);
            } else {
                Fxt.loadMask(waitMsg);
            }
        }
        Ext.Ajax.request({
            url: config.url,
            params: config.params,
            method: config.method || 'POST',
            callback: function(options, success, response) {
                if (waitMsg) {
                    if (maskCmp) {
                        maskCmp.setLoading(false);
                    } else {
                        Fxt.loadMask(false);
                    }
                }
                (config.afterload || Fxt.emptyFn)();
                var json = Ext.decode(response.responseText),
                    retcode = json.retcode;
                switch (retcode) {
                    case 'OK':
                        (config.success || Fxt.emptyFn)(json.data);
                        break;
                    case 'ERROR':
                        Fxt.alertError(json.message);
                        break;
                    default:
                        (config.failure || Fxt.emptyFn)(retcode, json.message, json.data);
                }
            }
        });
    },
    get: function(url, params, success, failure) {
        Fxt.ajax({
            url: url,
            method: 'GET',
            params: params,
            success: success,
            failure: failure
        });
    },
    post: function(url, params, success, failure) {
        Fxt.ajax({
            url: url,
            method: 'POST',
            params: params,
            success: success,
            failure: failure
        });
    },
    _defaultSubmitFailure: function(form, action) {
        var retcode = action.result.retcode;
        if (retcode == 'ERROR') {
            Fxt.alertError(action.result.message);
            return;
        }
        Fxt.alertError(Retcode[retcode]);
    },
    alertInfo: function(msg) {
        Fxt.loadMask(false);
        Ext.MessageBox.show({
            buttons: Ext.MessageBox.OK,
            title: '操作提示',
            msg: msg
        });
    },
    alertText: function(msg) {
        Fxt.loadMask(false);
        Ext.MessageBox.show({
            buttons: Ext.MessageBox.OK,
            title: '返回数据',
            multiline: true,
            value: msg,
            defaultTextHeight: 300,
            width: 500
        });
    },
    alertError: function(msg) {
        Fxt.loadMask(false);
        Ext.MessageBox.show({
            buttons: Ext.MessageBox.OK,
            icon: Ext.MessageBox.ERROR,
            title: '错误提示',
            msg: msg
        });
    },
    success: function(msg) {
        Fxt.loadMask(false);
        iziToast.success({
            timeout: 1000,
            title: msg,
            position: 'topCenter'
        });
    },
    error: function(msg) {
        Fxt.loadMask(false);
        iziToast.error({
            timeout: 1000,
            title: msg,
            position: 'topCenter'
        });
    },
    hasClz: function(clz) {
        var keys = clz.split('.');
        var value = window;
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i];
            if (value[key]) {
                value = value[key];
            } else {
                return false;
            }
        }
        return true;
    },
    loadMask: function(arg) {
        Fxt.tp.setLoading(arg);
    },
    unSelectAll: function(grid) {
        grid.getSelectionModel().deselectAll();
    },
    requireWithLoading: function(cls, callback) {
        Fxt.loadMask('加载中');
        Ext.require(cls, function() {
            Fxt.loadMask(false);
            callback.apply(this, arguments);
        });
    }
});

// 默认超时时间
Ext.Ajax.timeout = 120 * 1000;

Ext.define('Fxt.view.BaseCombo', {
    extend: 'Ext.form.ComboBox',
    displayField: 'value',
    valueField: 'key',
    queryMode: 'local',
    editable: false,

    $fields: ['key', 'value'],
    $autoLoad: false,
    $cascade: false,
    $cascadeKey: 'key',

    __edit: true,
    initComponent: function() {
        var combo = this;
        var $fields = combo.$fields;
        var $url = combo.$url;
        var $autoLoad = combo.$autoLoad;
        var $minChars = combo.$minChars;
        Ext.apply(combo, {
            store: {
                fields: $fields,
                autoLoad: $autoLoad,
                proxy: {
                    url: $url,
                    type: 'ajax',
                    actionMethods: 'post',
                    pageParam: false,
                    startParam: false,
                    limitParam: false,
                    reader: {
                        type: 'json',
                        root: 'data'
                    }
                }
            }
        });
        var $cascade = combo.$cascade;
        var $cascadeKey = combo.$cascadeKey;
        if ($cascade) {
            combo.addListener({
                change: function(self, newValue, oldValue, eOpts) {
                    if (this._onChange) {
                        var ret = this._onChange(self, newValue, oldValue, eOpts);
                        if (!ret) {
                            return;
                        }
                    }
                    var key = this.getValue(),
                        nextCombo = this.next();
                    if (this.__edit) {
                        this.__edit = false;
                    } else {
                        nextCombo.reset();
                    }
                    nextCombo.getStore().getProxy().setExtraParam($cascadeKey, key);
                    nextCombo.getStore().reload();
                }
            });
        }
        if ($minChars !== undefined) {
            combo.minChars = $minChars;
            combo.editable = true;
            combo.queryMode = 'remote';
        }
        this.callParent(arguments);
    }
});

Ext.define('Fxt.view.IdField', {
    extend: 'Ext.form.field.Hidden',
    alias: 'widget.idfield',
    name: 'id'
});

Ext.define('Fxt.form.field.Checkbox', {
    extend: 'Ext.form.field.Checkbox',
    alias: 'widget.fxtcheckbox',
    inputValue: 1
});

Ext.define('Fxt.view.BooleanCombo', {
    extend: 'Ext.form.ComboBox',
    alias: 'widget.booleancombo',
    displayField: 'value',
    valueField: 'key',
    store: {
        type: 'array',
        fields: ['key', 'value'],
        data: [
            [
                '', '全部'
            ],
            [
                1, '是'
            ],
            [
                0, '否'
            ]
        ]
    }
});

Ext.define('Fxt.view.DateRange', {
    extend: 'Ext.form.FieldContainer',
    alias: 'widget.daterange',
    layout: 'column',
    initComponent: function() {
        var name = this.name;
        var names = this.$names || [];
        var group = this.group;

        var name1 = names[0] || name;
        var name2 = names[1] || name;

        var items = [{
            xtype: 'datefield',
            operation: 'GE',
            name: name1,
            columnWidth: 0.5,
            format: 'Y-m-d',
            group: group
        }, {
            xtype: 'datefield',
            operation: 'LT',
            name: name2,
            columnWidth: 0.5,
            format: 'Y-m-d',
            group: group
        }];
        this.items = items;
        this.callParent(arguments);
    }
});

Ext.override(Ext.grid.column.Boolean, {
    trueText: 'Yes',
    falseText: 'No'
});

Ext.apply(Ext.form.field.VTypes, {
    daterange: function(val, field) {
        return true;
    },
    daterangeText: 'Start date must be less than end date',

    password: function(val, field) {
        return val == field.prev().getValue();
    },
    passwordText: '确认密码和新密码不一致'
});
Ext.define('Fxt.core.Controller', {
    extend: 'Ext.app.Controller',
    // 只执行一次
    init: function(options) {
        var me = this;
        me.control({
            "button[action=add]": {
                click: me.$doAdd
            },
            "button[action=edit]": {
                click: me.$doEdit
            },
            "button[action=delete]": {
                click: me.$doRemove
            },
            "button[action=query]": {
                click: me.$doQuery
            },
            "button[action=export]": {
                click: me.$doExport
            }
        });
        me.$onInit();
    },
    control: function(actions) {
        var me = this;
        if (Ext.isObject(actions)) {
            var obj = {};
            Ext.Object.each(actions, function(selector) {
                var s = "#" + me.$getViewport().id + " " + selector;
                obj[s] = actions[selector];
            }, me);
            me.callParent([obj]);
        } else {
            me.callParent(arguments);
        }
    },

    $doAdd: Fxt.emptyFn,

    $doEdit: Fxt.emptyFn,

    $doRemove: Fxt.emptyFn,

    $doQuery: Fxt.emptyFn,

    $doExport: Fxt.emptyFn,

    // 只执行一次
    $onInit: Fxt.emptyFn,

    // 每次打开执行一次
    $doInit: Fxt.emptyFn,

    $onViewportAfterrender: function() {
        Fxt.loadMask(false);
    },

    $getViewport: function() {
        return this.$viewport;
    },

    $setViewport: function(options) {
        var me = this;
        me.$viewport = Ext.create(me.$getModule() + '.view.Viewport', options || {});
        me.$viewport.on('afterrender', Ext.bind(me.$onViewportAfterrender, me));
    },

    $reloadGrid: function() {
        var me = this;
        try {
            me.$getViewport().$getGrid().getStore().reload();
        } catch (e) {
            // ignore
        }
    },

    $getModule: function() {
        var me = this;
        var clzName = Ext.getClassName(me);
        return clzName.substring(0, clzName.lastIndexOf('.'));
    },

    $getTitle: function() {
        return this.title || 'Unknown';
    }

});
Ext.define('Fxt.core.CrudController', {
    extend: 'Fxt.core.Controller',
    $doAddEditShare: true,
    $onViewportAfterrender: function() {
        var me = this;
        if (me.$getViewport().$getQueryForm()) {
            me.$getViewport().$getQueryForm().$onClickVariantBtn = function() {
                me.$doQuery();
            };
            Ext.create('Ext.util.KeyMap', {
                target: me.$getViewport().$getQueryForm().getId(),
                key: Ext.EventObject.ENTER,
                fn: function() {
                    me.$doQuery();
                }
            });
        }
        me.callParent(arguments);
    },
    $doQuery: function() {
        var me = this,
            form = me.$getViewport().$getQueryForm(),
            grid = me.$getViewport().$getGrid(),
            store = grid.getStore();
        if (form && form.isValid()) {
            filters = form.getFilters();
            store.getProxy().setExtraParam('filters', filters);
            store.loadPage(1);
            Fxt.unSelectAll(grid);
        }
    },
    $doExport: function(btn) {
        var me = this,
            grid = me.$getViewport().$getGrid(),
            store = grid.getStore(),
            form = me.$getViewport().$getQueryForm(),
            sorters = store.getSorters();
        Fxt.exportForm.getForm().setValues({
            'filters': form.getFilters(),
            'sort': Ext.encode(sorters)
        });
        Fxt.exportForm.doExport(Fxt.path + btn.$url);
    },
    $doAdd: function(btn) {
        var me = this,
            module = me.$getModule(),
            title = me.$getTitle(),
            clz = me.$doAddEditShare ? '.view.EditForm' : '.view.AddForm',
            grid = me.$getViewport().$getGrid();
        grid.setLoading('加载中...');
        Ext.require(module + clz, function() {
            grid.setLoading(false);
            var form = Ext.create(module + clz);
            var win = Ext.create('Fxt.core.view.Window', {
                title: '新增' + title,
                items: [form],
                buttons: [{
                    text: '保存',
                    handler: function() {
                        me.$saveModel(win, btn);
                    }
                }]
            });
        });
    },
    $doEdit: function(btn) {
        var me = this,
            module = me.$getModule(),
            grid = me.$getViewport().$getGrid(),
            title = me.$getTitle();
        Fxt.selectOneRow(grid, function(rec) {
            grid.setLoading('加载中...');
            Ext.require(module + '.view.EditForm', function() {
                grid.setLoading(false);
                var form = Ext.create(module + '.view.EditForm');
                if (btn.$fetchUrl) {
                    form.setLoading('数据加载中...');
                    Fxt.ajax({
                        url: Fxt.path + btn.$fetchUrl,
                        params: {
                            id: rec.get('id')
                        },
                        success: function(data) {
                            form.setLoading(false);
                            form.getForm().setValues(data);
                        }
                    });
                } else {
                    form.loadRecord(rec);
                }
                var win = Ext.create('Fxt.core.view.Window', {
                    title: '编辑' + title,
                    items: [form],
                    buttons: [{
                        text: '保存',
                        handler: function() {
                            me.$doEditModel(win, btn);
                        }
                    }]
                });
            });
        });
    },
    $doRemove: function(btn) {
        var me = this,
            grid = me.$getViewport().$getGrid(),
            selModel = grid.getSelectionModel(),
            selCount = selModel.getCount();
        if (selCount === 0) {
            Ext.Msg.alert('提示', '选择一行');
            return false;
        }
        var selRows = selModel.getSelection();
        var ids = [];
        Ext.each(selRows, function(row) {
            ids.push(row.get('id'));
        });
        Ext.Msg.confirm('提示', '确认删除' + ' ' + ids.length + ' 行', function(ok) {
            if (ok != 'yes') {
                return;
            }
            grid.setLoading('删除中...');
            Fxt.ajax({
                url: Fxt.path + btn.$url,
                params: {
                    ids: ids.join(',')
                },
                success: function(data) {
                    grid.setLoading(false);
                    Ext.Msg.alert('提示', '删除成功', function() {
                        grid.getStore().reload();
                    });
                }
            });
        });
    },
    $doEditModel: function(win, btn) {
        var me = this,
            form = win.down('form');
        if (form.isValid()) {
            form.getForm().submit({
                waitMsg: '正在保存...',
                url: Fxt.path + btn.$url,
                success: function() {
                    win.close();
                    me.$doQuery();
                    me.$getViewport().$getGrid().getSelectionModel().deselectAll();
                },
                failure: Fxt._defaultSubmitFailure
            });
        }
    },
    $saveModel: function(win, btn) {
        var me = this,
            form = win.down('form');
        if (form.isValid()) {
            form.getForm().submit({
                waitMsg: '正在保存...',
                url: Fxt.path + btn.$url,
                success: function() {
                    win.close();
                    me.$doQuery();
                    Fxt.alertInfo('保存成功');
                },
                failure: Fxt._defaultSubmitFailure
            });
        }
    }
});
Ext.define('Fxt.core.Model', {
    extend: 'Ext.data.Model'
});
Ext.define("Fxt.core.Store", {
	extend: "Ext.data.Store",
	autoLoad: false,
	remoteSort: true,
	$paging: true,
	constructor: function(options) {
		var me = this;
		var $paging = me.$paging;
		Ext.apply(me, options || {});
		me.proxy = {
			type: "ajax",
			url: Fxt.path + me.$url,
			reader: {
				type: 'json',
				root: $paging ? 'data.list' : 'data',
				totalProperty: $paging ? 'data.total' : ''
			}
		};
		me.callParent(arguments);
	}
});
Ext.define("Fxt.core.TreeStore", {
	extend: "Ext.data.TreeStore",
	constructor: function() {
		var me = this;
		me.proxy = {
			type: "ajax",
			url: Fxt.path + me.$url,
			params: this.$params,
			reader: {
				type: 'json'
			}
		};
		me.callParent(arguments);
	},
	root: {
		text: 'Root',
		id: '-1'
	}
});
Ext.define('Fxt.form.Panel', {
    extend: 'Ext.form.Panel',
    defaultType: 'textfield',
    layout: {
        type: 'anchor'
    },
    split: true,
    border: false,
    defaults: {
        frame: false,
        border: false,
        padding: '5'
    },
    buttonAlign: 'left',
    autoScroll: true
});
Ext.define('Fxt.core.view.Window', {
    extend: 'Ext.window.Window',
    autoShow: true,
    layout: 'fit',
    bodyPadding: 10,
    modal: true,
    $closeBtn: true,
    initComponent: function() {
        var me = this;
        var btns = me.buttons || [];

        if (me.$closeBtn) {
            btns.push({
                text: '关闭',
                handler: function() {
                    this.up('window').close();
                }
            });
        }

        Ext.apply(me, {
            buttons: btns
        });

        me.callParent(arguments);
    },
    $onAfterrender: function() {
        var me = this;

        var form = me.down('form');

        if (form) {
            var child = form.child();
            while (1) {
                if (child && !child.isHidden()) {
                    child.focus();
                    break;
                }
                child = child.next();
                if (!child) {
                    break;
                }
            }
        }
    },
    listeners: {
        afterrender: function() {
            var me = this;
            me.focus();
            me.$onAfterrender();
        }
    }
});
Ext.define('Fxt.core.view.Viewport', {
	extend: 'Ext.panel.Panel',
	layout: "border",
	autoScroll: false,
	initComponent: function() {
		this.items = this.$buildItems();

		this.callParent(arguments);
	},
	$buildItems: function() {
		return [{
			region: "center",
			border: false,
			html: "Please override the '$buildItems' method in your subclass!"
		}];
	}
});
Ext.define('Fxt.core.view.CrudViewport', {
    extend: 'Fxt.core.view.Viewport',
    $createQueryForm: Fxt.emptyFn,
    $createGrid: Fxt.emptyFn,
    $getQueryForm: function() {
        return this.$_queryForm;
    },
    $getGrid: function() {
        return this.$_grid;
    },
    $buildItems: function() {
        var me = this;
        me.$_queryForm = me.$createQueryForm();
        me.$_grid = me.$createGrid();

        var items = [];
        if (me.$getQueryForm()) {
            items.push(me.$getQueryForm());
        }
        if (me.$getGrid()) {
            items.push(me.$getGrid());
        }
        return items;
    }
});
Ext.define('Fxt.core.view.AddForm', {
    extend: 'Ext.form.Panel',
    bodyPadding: 20,
    border: false,
    layout: 'anchor',
    defaults: {
        xtype: 'textfield',
        anchor: '100%',
        labelWidth : '25%'
    }
});
Ext.define('Fxt.core.view.EditForm', {
    extend: 'Ext.form.Panel',
    bodyPadding: 20,
    border: false,
    layout: 'anchor',
    defaults: {
        xtype: 'textfield',
        anchor: '100%',
        labelWidth: '25%'
    },
    $doEdit: true,
    initComponent: function() {
        var me = this;

        var $doEdit = me.$doEdit;
        Ext.each(me.items, function(item) {
            if (item.$disabled === true) {
                item.disabled = $doEdit;
            }
        });
        me.callParent(arguments);
    }
});
Ext.define('Fxt.core.view.Grid', {
    extend: 'Ext.grid.Panel',
    border: false,
    $audit: true,
    $paging: true,
    $checkbox: true,
    $selModel: 'SINGLE',
    viewConfig: {
        enableTextSelection: true
    },
    initComponent: function() {
        var me = this,
            $audit = me.$audit,
            $paging = me.$paging,
            $checkbox = me.$checkbox,
            $selectKey = me.$selectKey,
            $selModel = me.$selModel;
        Ext.each(me.columns, function(col) {
            if (!col.width) {
                col.width = Fxt.getCmpWidth(me, col.dataIndex);
            }                
        });
        if ($audit) {
            me.columns = Ext.Array.union(me.columns, [{
                text: 'createdBy',
                dataIndex: 'createdBy',
                width: Fxt.getCmpWidth(me, 'createdBy')
            }, {
                text: 'createdDate',
                dataIndex: 'createdDate',
                width: Fxt.getCmpWidth(me, 'createdDate')
            }, {
                text: 'modifiedBy',
                dataIndex: 'modifiedBy',
                width: Fxt.getCmpWidth(me, 'modifiedBy')
            }, {
                text: 'modifiedDate',
                dataIndex: 'modifiedDate',
                width: Fxt.getCmpWidth(me, 'modifiedDate')
            }]);
        }
        me.store = me.$newStore();
        if ($selectKey) {
            me.getNewSelectIds = function() {
                var ids = [];
                var store = me.getStore();
                var selectModels = me.getSelectionModel().getSelection();
                Ext.each(selectModels, function(record) {
                    var id = record.get('id');
                    var model = store.getById(id);
                    if (model.get($selectKey) == false) {
                        ids.push(id);
                    }
                });
                return ids;
            };
            me.getNewUnSelectIds = function() {
                var ids = [];
                var store = me.getStore();
                var selectModels = me.getSelectionModel().getSelection();
                store.each(function(record) {
                    if (record.get($selectKey) == true) {
                        var id = record.get('id');
                        var exists = false;
                        Ext.each(selectModels, function(selectModel) {
                            if (id == selectModel.get('id')) {
                                exists = true;
                                return false;
                            }
                        });
                        if (!exists) {
                            ids.push(id);
                        }
                    }
                });
                return ids;
            };
        }
        if ($checkbox) {
            me.selModel = Ext.create('Ext.selection.CheckboxModel', {
                mode: $selModel
            });
        }
        if ($paging) {
            Ext.apply(this, {
                bbar: {
                    xtype: 'pagingtoolbar',
                    store: me.store,
                    displayInfo: true
                }
            });
        }
        me.addListener('columnresize', Ext.bind(Fxt.gridColumnResize, me));
        me.callParent(arguments);
    },
    $newStore: Fxt.emptyFn
});
Ext.define('Fxt.core.view.QueryForm', {
    extend: 'Fxt.form.Panel',
    layout: 'column',
    $variantBtns: [],
    getFilters: function() {
        var form = this;
        var fields = form.getForm().getFields();
        var obj = {};
        fields.each(function(item) {
            if (Ext.isEmpty(item.getValue())) {
                if (item.empty2Null) {
                    obj[item.name] = '__NULL__';
                }
            } else if (item.getValue() != '__ALL__') {
                //不包括的表单
                if (!item.ignore) {
                    var value = item.getValue();
                    obj[item.name] = value;
                }
            }
        });
        return Ext.encode(obj);
    },
    initComponent: function() {
        var me = this;
        var btns = [];
        btns.push({
            text: 'Query',
            action: 'query'
        });
        if (me.$variantBtns && me.$variantBtns.length > 0) {
            Ext.each(me.$variantBtns, function(btn, index) {
                btn.handler = function() {
                    me.getForm().reset();
                    me.getForm().setValues(btn.values);
                    if (me.$onClickVariantBtn && typeof(me.$onClickVariantBtn) == 'function') {
                        me.$onClickVariantBtn(btn, me);
                    }
                };
            });
            var variantSplitBtn = {
                xtype: 'splitbutton',
                text: '变式',
                menu: me.$variantBtns
            };
            btns.push(variantSplitBtn);
        }
        btns.push({
            text: 'Reset',
            handler: function() {
                me.getForm().reset();
            },
            margin: "0 50 0 0"
        });
        Ext.apply(this, {
            buttons: btns
        });
        this.callParent(arguments);
    }
});
Ext.define('Fxt.core.view.TreeGrid', {
    extend: 'Ext.tree.Panel',
    rootVisible: false,
    sortableColumns: false,
    $cascadeCheck: true,
    initComponent: function() {
        var me = this;

        if (me.$tbar) {
            me.tbar = Ext.Array.union(me.tbar, me.$tbar);
        }

        me.store = me.$newStore();
        if (me.$cascadeCheck) {
            me.on('checkchange', function(node, checked, eOpts) {
                node.cascadeBy(function(n) {
                    n.set('checked', checked);
                });
                var p = node.parentNode;
                var eachChild = function(c) {
                    if (!c.get('checked')) {
                        pChecked = false;
                        return false;
                    }
                };
                while (p) {
                    var pChecked = true;
                    p.eachChild(eachChild);
                    p.set('checked', pChecked);

                    p = p.parentNode;
                }
            });
        }

        me.callParent(arguments);
    },
    $checkAll: function() {
        
    },
    $newStore: Fxt.emptyFn
});
Ext.define('Fxt.index.model.Menu', {
	extend: 'Ext.data.Model',
	fields: ['id', 'name', 'value', 'text']
});
Ext.define('Fxt.index.store.MenuPanel', {
	extend: 'Fxt.core.TreeStore',
	model: 'Fxt.index.model.Menu',
	root: Fxt.menuData
});
Ext.define('Fxt.index.view.MenuPanel', {
	extend: 'Ext.tree.Panel',
	alias: 'widget.index-menupanel',
	rootVisible: false,
	expand: true,
	useArrows: true
});
Ext.define('Fxt.index.view.TabPanel', {
	extend: 'Ext.tab.Panel',
	border: false
});
Ext.require(['Fxt.index.view.TabPanel', 'Fxt.index.view.MenuPanel', 'Fxt.index.store.MenuPanel'], function() {
    Fxt.tp = Ext.create('Fxt.index.view.TabPanel', {
        region: 'center',
        plugins: Ext.create('Ext.ux.TabCloseMenu')
    });

    Fxt.mp = Ext.create('Fxt.index.view.MenuPanel', {
        store: Ext.create('Fxt.index.store.MenuPanel'),
        region: 'west',
        width: Fxt.menuWidth || 280,
        split: true,
        collapsible: true,
        title: '菜单'
    });

    Fxt.exportForm = Ext.create('Ext.form.Panel', {
        standardSubmit: true,
        hidden: true,
        defaultType: 'textfield',
        items: [{
            name: 'filters'
        }, {
            name: 'sort'
        }],
        doExport: function(url, params) {
            var form = this;
            form.getForm().submit({
                url: url,
                params: params
            });
        }
    });

    Ext.define('Fxt.index.view.Viewport', {
        extend: 'Ext.container.Viewport',
        layout: 'border',
        items: [
            Fxt.tp,
            Fxt.mp, {
                height: 0,
                xtype: 'panel',
                region: 'south',
                items: [Fxt.exportForm]
            }
        ]
    });
});
Fxt.addTab = function(record) {
    var id = record.id,
        tab = Fxt.tp.queryById(id);
    if (tab) {
        Fxt.tp.setActiveTab(id);
        return;
    }
    var title = record.title;
    // Viewport渲染完，会关闭
    Fxt.loadMask('正在加载 ' + title + ' 页面, 请等待...');
    var ctrlId = 'ctrl-' + id,
        ctrl = Fxt.app.controllers.get(ctrlId);
    var viewportConfig = {
        title: title,
        id: id,
        closable: true
    };
    var ctrlClz = 'Fxt.' + record.module + '.Controller';
    Ext.require(ctrlClz, function() {
        if (!ctrl) {
            ctrl = Ext.create(ctrlClz, {
                id: ctrlId
            });
            ctrl.title = ctrl.title || title;
            Fxt.app.controllers.add(ctrl);
            ctrl.$setViewport(viewportConfig);
            ctrl.init();
        } else {
            ctrl.$setViewport(viewportConfig);
        }
        Fxt.tp.add(ctrl.$viewport);
        ctrl.$doInit(record.bundle);
        Fxt.tp.setActiveTab(id);
    });
};
Ext.define('Fxt.index.Controller', {
    extend: 'Ext.app.Controller',
    stores: ['Fxt.index.store.MenuPanel'],
    models: ['Fxt.index.model.Menu'],
    views: ['Fxt.index.view.TabPanel', 'Fxt.index.view.MenuPanel', 'Fxt.index.view.Viewport', 'Ext.ux.TabCloseMenu'],
    init: function() {
        Fxt.mp.addListener({
            'itemclick': function(panel, record, item, index) {
                var id = record.get('id');
                var store = this.getStore();
                var node = store.getNodeById(id);
                if (!node.isLeaf()) {
                    return false;
                }
                Fxt.addTab({
                    id: record.get('id'),
                    title: record.get('text'),
                    module: Fxt.buildNodePkg(node)
                });
            }
        });
    }
});